package com.study.english.util;

import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;

@Slf4j
public class VideoToImage {

    /**
     * 获取指定视频的帧并保存为图片至指定目录
     *
     * @param videofile 源视频文件路径
     * @param framefile 截取帧的图片存放路径
     * @throws Exception
     */
    public static void fetchFrame(String videofile, String framefile)
            throws Exception {
        long start = System.currentTimeMillis();
        File targetFile = new File(framefile);
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile);
        ff.start();
        long lengthInTime = ff.getLengthInTime();
        System.out.println(lengthInTime);
        int lenght = ff.getLengthInFrames();
        int i = 0;
        Frame f = null;
        while (i < lenght) {
            // 过滤前5帧，避免出现全黑的图片，依自己情况而定
            f = ff.grabFrame().clone();
            if ((i > 500) && (f.image != null)) {
                break;
            }
            i++;
        }
        int owidth = f.imageWidth;
        int oheight = f.imageHeight;
        // 对截取的帧进行等比例缩放
        int width = 800;
        int height = (int) (((double) width / owidth) * oheight);
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
        BufferedImage renderedImage = new Java2DFrameConverter().getBufferedImage(f);
        bi.getGraphics().drawImage(renderedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH),
                0, 0, null);
        ImageIO.write(bi, "jpg", targetFile);
        //ff.flush();
        ff.stop();
        System.out.println(System.currentTimeMillis() - start);
    }


    /**
     * 获取指定视频的时长
     *
     * @param videofile 源视频文件路径.可以时http
     * @throws Exception
     */
    public static Long videoPlayTime(String videofile) {
        //要装2010 c++ microsof visual C++   2010   x64
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile);
        Long lengthInTime = 0l;
        try {
            ff.start();
            lengthInTime = ff.getLengthInTime();
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return lengthInTime;
    }

    /**
     * 获取指定视频的帧并保存为base64图片
     *
     * @param videoFile 源视频文件路径
     *                  frameNum 帧数
     *                  width 宽度，  注意，设置好宽度后，高度安装比例取值，
     * @throws Exception
     */
    public static String videoToBase64Image(String videoFile, Long frameNum, Integer width) {
        ByteArrayOutputStream byteArrayInputStream = new ByteArrayOutputStream();
        try {
            FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
            ff.start();
            int lenght = ff.getLengthInFrames();
            Long i = 0l;
            Frame f = null;
            while (i < lenght) {
                f = ff.grabFrame().clone();
                if ((i > frameNum) && (f.image != null)) {
                    break;
                }
                i++;
            }
            int owidth = f.imageWidth;
            int oheight = f.imageHeight;
            // 对截取的帧进行等比例缩放
            int height = (int) (((double) width / owidth) * oheight);
            BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
            BufferedImage renderedImage = new Java2DFrameConverter().getBufferedImage(f);
            bi.getGraphics().drawImage(renderedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH),
                    0, 0, null);
            ImageIO.write(bi, "jpg", byteArrayInputStream);
            ff.stop();
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        byte[] bytes = byteArrayInputStream.toByteArray();
        BASE64Encoder base64Encoder = new BASE64Encoder();
        String jpgBase64 = base64Encoder.encodeBuffer(bytes).trim();
        jpgBase64 = jpgBase64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
        System.out.println(videoFile);
        System.out.println("值为：" + "data:image/jpg;base64," + jpgBase64);
        return "data:image/jpg;base64," + jpgBase64;
    }

    /**
     * 获取指定视频的帧并保存为Base64图片
     *
     * @param videoFile 源视频文件路径
     *                  frameNum 帧数
     *                  width 宽度，  注意，设置好宽度后，高度安装比例取值，
     * @throws Exception
     */
    public static ByteArrayInputStream videoToByteArrayOutputStreamImage(String videoFile, Long frameNum, Integer width) {
        ByteArrayOutputStream byteArrayInputStream = new ByteArrayOutputStream();
        ByteArrayInputStream bis = null;
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
        try {
            ff.start();
            ff.setFrameNumber(Integer.parseInt(frameNum.toString()));
            Frame f = ff.grabImage();
            // 对截取的帧进行等比例缩放
            BufferedImage bi = new BufferedImage(width, width, BufferedImage.TYPE_3BYTE_BGR);
            BufferedImage renderedImage = new Java2DFrameConverter().getBufferedImage(f);
            bi.getGraphics().drawImage(renderedImage.getScaledInstance(width, width, Image.SCALE_SMOOTH),
                    0, 0, null);
            ImageIO.write(bi, "jpg", byteArrayInputStream);
            ff.release();
            ff.stop();
            bis = new ByteArrayInputStream(byteArrayInputStream.toByteArray());
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return bis;
    }

    public static void main(String[] args) {
        try {
            VideoToImage.fetchFrame("http://192.168.152.128:9000/wftest/eee/CE001MuddyPuddles[www19937com]/CE001MuddyPuddles[www19937com].mp4", "D:/new/test4.jpg");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
